import Core.Gadget as Gadget
import Core.WindFunctions as Wind
import Core.MySQLDB as MySQLDB
import datetime
import DataProcess
import os
from Factors_Systematic.General import *

# ---Statistics---
def Statistics():
    count = 0
    bonds = []
    countExchange = {}
    other = 0
    instruments = database.find("Instruments", "BondMap")
    for instrument in instruments:
        count += 1
        if count % 100 == 0:
            print(count, "/", len(instruments))
        major = instrument["MajorSymbol"]
        symbol = instrument["Symbol"]
        exchange = symbol[-2:]
        if exchange not in countExchange:
            countExchange[exchange] = 0
        countExchange[exchange] += 1

        if exchange == "SH" or exchange == "SZ":
            if major not in bonds:
                bonds.append(major)

    print(countExchange)
    k = 0


def FixMajorSymbol():
    count = 0
    bondByMajorSymbol = {}

    instruments = database.find("Instruments", "BondMap")
    for instrument in instruments:
        count += 1
        if count % 100 == 0:
            print(count, "/", len(instruments))
        major = instrument["MajorSymbol"]
        symbol = instrument["Symbol"]

        #
        if major not in bondByMajorSymbol:
            bondByMajorSymbol[major] = []

        if symbol not in bondByMajorSymbol[major]:
            bondByMajorSymbol[major].append(symbol)

    #
    countExchange = {}
    for major, codes in bondByMajorSymbol.items():
        exchange = major[-2:]
        if exchange not in countExchange:
            countExchange[exchange] = 0
        countExchange[exchange] += 1
    print(countExchange)

    #
    count = 0
    fixedBondByMajorSymbol = {}
    for major, codes in bondByMajorSymbol.items():
        #
        count += 1
        #if count % 100 == 0:
        #    print(count, "/", len(bondByMajorSymbol))

        priority = [None,None,None,None]
        for code in codes:
            exchange = code[-2:]
            newMajor = None
            if exchange == "IB":
                priority[0] = code
                break
            elif exchange == "SH":
                priority[1] = code
            elif exchange == "SZ":
                priority[2] = code
            else:
                priority[3] = code

        newMajor = None
        for i in range(4):
            if priority[i] != None:
                newMajor = priority[i]
                break

        newExchange = newMajor[-2:]
        if newExchange != "IB":
            print("NonIB", newMajor)
        fixedBondByMajorSymbol[newMajor] = codes

    #
    #
    countExchange = {}
    for major, codes in fixedBondByMajorSymbol.items():
        print(major,codes)
        for code in codes:
            database.update("Instruments", "BondMap", {"Key":code}, {"MajorSymbol":major})
        exchange = major[-2:]
        if exchange not in countExchange:
            countExchange[exchange] = 0
        countExchange[exchange] += 1
    print(countExchange)

    k = 0


def TransitFromMongoToMySql(database, mysql):
    count = 0
    instruments = database.find("Instruments", "BondMap")
    for instrument in instruments:
        count += 1
        if count % 100 == 0:
            print(count, "/", len(instruments))
        major = instrument["MajorSymbol"]
        symbol = instrument["Symbol"]
        document = {}
        document["Symbol"] = symbol
        document["MajorSymbol"] = major
        document["Key"] = symbol
        mysql.Insert("Instruments","BondMap",document)
        k = 0


def Download_TBond_Issue_Reduction(database, datetime1, datetime2):
    # Total 55%
    # 存量统计 "国债" 16.5, "地方政府债" 23.05, "央行票据" 0.02, "政策银行债" 15.84%
    bond_types = ["国债", "地方政府债", "央行票据", "政策银行债"]
    #
    for bond_type in bond_types:
        Download_Bond_Issue_Reduction(database, datetime1, datetime2, bond_type)


def Download_Credit_Bond_Issue_Reduction(database, datetime1, datetime2):
    # Total 34%
    bond_types = []
    #
    bond_types.append("公司债") # 7.68
    bond_types.append("企业债") # 2.20
    bond_types.append("中期票据") # 7.06
    bond_types.append("短期融资券") # 2.20

    # 金融债
    bond_types.append("商业银行债") # 1.68
    bond_types.append("商业银行次级债券") # 1.68
    bond_types.append("保险公司债") # 0.31
    bond_types.append("证券公司债") # 1.36
    bond_types.append("证券公司短期融资券") # 0.23
    bond_types.append("其它金融机构债") # 0.64

    # 其他融资工具
    bond_types.append("资产支持证券")  # 3.5
    bond_types.append("政府支持机构债")  # 1.59 # 类似于金融债
    bond_types.append("定向工具")  # PPN  2.1 # 类似于信用债
    #
    for bond_type in bond_types:
        Download_Bond_Issue_Reduction(database, datetime1, datetime2, bond_type)
        a = 0


def Download_Bond_Issue_Reduction(database, datetime1, datetime2, bond_type):
    #
    print("Download_Bond_Issue_Reduction from", datetime1, datetime2, bond_type)
    #
    sDateTime1 = Gadget.ToDateString(datetime1)
    sDateTime2 = Gadget.ToDateString(datetime2)
    #
    field_map= {}
    field_map["startdate"] = "start_date" # "开始日期"
    field_map["enddate"] = "end_date" # "结束日期"
    #
    field_map["totalissuevolume"] = "total_issue_amount" # "发行总量（亿元）"
    field_map["issueamount"] = "total_issue_number" # "发行只数"
    #
    field_map["totalredemption"] = "total_reduction_amount" # 偿还总量（亿元）
    field_map["netfinancingamount"] = "net_issue_amount" # 净融资额（亿元）
    #
    field_map["redemptionatmaturity"] = "matured_amount" # "到期偿还金额（亿元）"
    field_map["maturedamount"] = "matured_number" # "到期只数"
    field_map["earlyredemption"] = "early_redemption_amount" # "提前兑付量（亿元）"
    field_map["earlyredeemedamount"] = "early_redemption_number" # "提前兑付只数"
    field_map["putbackvolume"] = "buyback_amount" # 回售金额（亿元）
    field_map["putbackamount"] = "buyback_number" # 回售只数
    field_map["callvolume"] = "call_amount" # 赎回金额（亿元）, 含有Callable赎回条款的
    field_map["callamount"] = "call_number" # 赎回只数

    # ---Request Data---
    # frequency=日;
    # maingrade=全部; # 主体评级
    # zxgrade=全部; # 债项评级
    # datetype=发行起始; # 日期类型：发行起始，缴款日期，发行截止，公告日期，上市日期
    # type=默认; # 企业性质
    # bondtype=默认") # 债券类型：默认，全部
    date_type = "发行起始"
    #
    params = {}
    params["startdate"] = sDateTime1
    params["enddate"] = sDateTime2
    params["frequency"] = "日"
    params["maingrade"] = "全部"
    params["zxgrade"] = "全部"
    params["datetype"] = date_type
    params["type"] = "默认"
    params["bondtype"] = bond_type
    params["bondid"] = "1000013859000000" # 2020-8-24 新发现入参，相当于筛选范围是全部市场

    strParams = Wind.Build_Param_Str(params)
    wind_data = w.wset("bondissuanceandmaturity", strParams)

    if len(wind_data.Data) == 0:
        print("No Bond Issue Info from", datetime1, "to", datetime2)
        return

    # ---Build Dataframe---
    data_cache = {}
    for i in range(len(wind_data.Fields)):
        wind_field = wind_data.Fields[i]
        if wind_field not in field_map:
            print("No Map", wind_field)
            continue
        db_field = field_map[wind_field]
        data_cache[db_field] = wind_data.Data[i]

    df = pd.DataFrame(data_cache)

    #
    print(df[["start_date", "total_issue_amount", "total_reduction_amount", "net_issue_amount"]].tail(10))
    # df.to_csv("d://seo.csv")
    # df.fillna(0, inplace=True)

    # ---Save To Database---
    columns = df.columns
    newDocuments = []
    for index, row in df.iterrows():
        newDocument = {}
        for field in columns:
            value = row[field]
            newDocument[field] = value
            if isinstance(value, float) and np.isnan(value):
                newDocument[field] = None
            if value == "":
                newDocument[field] = None

        # 原则上全是空值，不预录入
        if bond_type !="全部" and newDocument["total_issue_amount"] == None and newDocument["total_reduction_amount"] == None:
            continue
        #
        newDocument["bond_type"] = bond_type
        newDocument["date_type"] = date_type
        #
        newDocument["Date"] = newDocument["end_date"]
        newDocument["DateTime"] = newDocument["end_date"]
        newDocument["Key2"] = newDocument["bond_type"] + "_" \
                              + newDocument["date_type"] + "_" \
                              + Gadget.ToDateString(newDocument["Date"])
        #
        newDocuments.append(newDocument)

    #
    print("Try to Upsert #", len(newDocuments), bond_type)
    database.Upsert_Many("bond", "issue_reduction", {}, newDocuments)
    print("Upsert Bond_Issue Info from", datetime1, "to", datetime2, "#", bond_type, len(newDocuments))
    #
    return df

def Test_Bond_Issue(database):

    datetime1 = datetime.datetime(2000,1,1)
    datetime2 = datetime.datetime(2020,7,1)

    # interest_start_date 相当于 issue_date
    date_field = "date"

    filter = []
    filter.append([date_field, ">=", datetime1])
    filter.append([date_field, "<=", datetime2])
    #
    documents = database.Find("Bond", "issue_reduction", filter)
    df = Gadget.DocumentsToDataFrame(documents)
    df["date"] = pd.to_datetime(df["date"])
    df.set_index("date", inplace=True)

    df_by_month = df[["total_reduction_amount", "net_issue_amount"]].resample("M").sum()
    print(df_by_month)


    # Gadget.AddMonthColumn(df, date_field=date_field)
    # df_by_month = df.groupby("Month").count()
    # print(df_by_month)
    # df_by_month2 = df.groupby("Month").sum()
    # print(df_by_month2)

    df_by_month.to_csv("d://bond_Total_Issue_by_month.csv")


def Automatic_Download_Bond_Misc(database, datetime2, startEntry=0):
    #
    if datetime2 == None:
        datetime2 = datetime.datetime.today()

    maxDate = database.ExecuteSQL("financial_data", "select max(date) from financial_data.bond_issue_reduction")
    maxDate = maxDate[0][0]
    tmp_datetime1 = maxDate - datetime.timedelta(days=30)
    tmp_datetime2 = datetime2 + datetime.timedelta(days=30)

    tmp_datetime1 = datetime.datetime(2020,4,30)

    # ---债券发行与赎回---
    Download_Bond_Issue_Reduction(database, tmp_datetime1, tmp_datetime2, bond_type="全部")
    Download_TBond_Issue_Reduction(database, tmp_datetime1, tmp_datetime2)
    Download_Credit_Bond_Issue_Reduction(database, tmp_datetime1, tmp_datetime2)


if __name__ == '__main__':
    #
    pathfilename = os.getcwd() + "\..\Config\config2.json"
    config = Config.Config(pathfilename)
    database = config.DataBase("JDMySQL")
    realtime = config.RealTime()

    w.start()

    datetime2 = datetime.datetime(2020, 8, 21)
    Automatic_Download_Bond_Misc(database, datetime2, startEntry=0)

    # datetime1 = datetime.datetime(2020, 6, 1)
    # datetime2 = datetime.datetime(2020, 8, 1)
    # Download_Bond_Issue_Reduction(database, datetime1, datetime2, bond_type="全部")
    # Download_TBond_Issue_Reduction(database, datetime1, datetime2)
    # Download_Credit_Bond_Issue_Reduction(database, datetime1, datetime2)

    # Test_Bond_Issue(database)

    # ---Test---
    data = DataProcess.Request_Bond_Info(["019568.SH"])

    # ---更新Bond列表---
    # DataProcess.Request_Write_Bond_List(mysql)

    # ---Test 下载bond详细信息---
    symbol = "018005.SH"
    DataProcess.Download_BondInfo(database, symbol)


    # ---Test 下载一个产品的Daily Bar---


    # ---冷启动历史数据库，下载DailyBar---
    # instruments = database.Find("Instruments", "Bond")
    # DataProcess.Download_Data(instruments, DataProcess.Download_DailyBars)

    # ---更新历史数据库，按照时间区间下载DailyBar---
    # datetime1 = Gadget.ToUTCDateTime(datetime.datetime(2018,10,8)) # 上次更新时间
    # datetime2 = Gadget.ToUTCDateTime(datetime.datetime.now()) # 当前时间
    # DataProcess.Download_Data2(instruments, DataProcess.Download_DailyBars)








